/**
  ETFRoot project, Anyang Normal University && IMP-CAS
  \class ETFVMEUnpacker
  \brief unpacker for raw data collected by VME daq
  NOTE that this is devised to be an abstract base class, since VME decoding
  implementation depends on the plugins, thus should be specially written for
  different VME plugin configurations. It is the user's responsibility to derive
  this class to implement for their own experiments.
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2021-09-27
  \date 2021-10-02 last modified
  \attention
  changelog
  <table>
  <tr>  <th>Date         <th>Author      <th>Description                   </tr>
  <tr>  <td>2021-09-27   <td>Asia Sun    <td>file created                  </tr>
  <tr>  <td>2021-10-01   <td>Asia Sun    <td>completing                    </tr>
  </table>

  \copyright Copyright (c) 2021 Anyang Normal U. && IMP-CAS with LGPLv3 LICENSE
*/

#ifndef ETFVMEUnpacker_h
#define ETFVMEUnpacker_h

#include "ETFUnpacker.h"
#include "vme_block_head.h"

class ETFVMEEvent;

using std::cout;
using std::endl;

class ETFVMEUnpacker : public ETFUnpacker{
public:
  ETFVMEUnpacker(); ///< type=0 is used to indicate VME daq
  virtual ~ETFVMEUnpacker();

  virtual bool Init(); ///< register the raw data item array
  virtual void Reset(); ///< clear the output before each event loop
  ///< do the unpack. \param nev: number of events to be analysed
  virtual bool DoUnpack(Int_t *data, Int_t nev){ return true; }
  virtual void ReadComment(FILE *file);
  virtual int GetOneEvent(FILE *file); ///< get 1 event to memory from file
  virtual int GetOneEvent(int *fstream); ///< get 1 event to memory from stream
  virtual bool Unpack(); ///< complete the unpacking to clones arrays
  const ETFVMEEvent *GetCurrentEvent() const{ return fEvent; }
  int GetBlockIndex() const{ return fBlockHead.index; }
  virtual void PrintSummary(); ///< print unpacking summary
  void SetDisplayComment(bool opt){ fDisplayComment = opt; }
  void SetDebug(bool opt){ fDebug = opt; }
  int GetNofProcessedBlock(){ return fBlockCnt; }

  static const int kBLKSIZE = 8192; ///< the lenght of a block in word (4bytes)

  ClassDef(ETFVMEUnpacker, 0); // unpacker for VME raw data

protected:
  virtual void Register(); ///< register the raw data to the output tree as branches
  /// customizable user event-decoding for a certain vme-config
  /// user to implement this method should be aware that the data to be decoded
  /// starts from fData[fPos+3] to fData[fPos+fEvent.fEventHead.event_length]
  virtual void UserDecode() = 0;

  vme_block_head fBlockHead;
  ETFVMEEvent *fEvent;

  int fData[kBLKSIZE]; ///< to store 1 block
  int fPos; // current position in the block
  int fIndex0; ///< the index of the first event, to make the indices starting from 0
  /// note that a block is fixed length (8192 bytes), may contain more than 1 event
  int fBlockCnt; ///< number of blocks processed

  bool fDisplayComment; ///< whether to display the comment

private:
  bool fDebug; // if debug or not
};

#endif
